package org.linlinjava.litemall.core.notify;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.print.util.FeieService;
import org.linlinjava.litemall.core.print.util.XinhuaService;
import org.linlinjava.litemall.core.redis.RedisCache;
import org.linlinjava.litemall.core.task.OrderUnpaidTask2;
import org.linlinjava.litemall.core.task.TaskService;
import org.linlinjava.litemall.core.task.printSnTaskService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Message;
import org.linlinjava.litemall.db.dao.SysPushMsgMapper;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
import org.linlinjava.litemall.db.domain.LitemallShop;
import org.linlinjava.litemall.db.domain.LitemallUser;
import org.linlinjava.litemall.db.domain.SysPushMsg;
import org.linlinjava.litemall.db.domain.SysUser;
import org.linlinjava.litemall.db.domain.UserVo;
import org.linlinjava.litemall.db.domain.WxUser;
import org.linlinjava.litemall.db.service.LitemallAdminService;
import org.linlinjava.litemall.db.service.LitemallOrderGoodsService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.db.service.LitemallShopService;
import org.linlinjava.litemall.db.service.LitemallUserService;
import org.linlinjava.litemall.db.service.SysUserService;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.StringUtils;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.starter.TioWebSocketServerBootstrap;

import com.alibaba.fastjson.JSONArray;
import com.gexin.fastjson.JSONObject;
import com.gexin.rp.sdk.base.IBatch;
import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.SingleMessage;
import com.gexin.rp.sdk.base.impl.Target;
import com.gexin.rp.sdk.exceptions.RequestException;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.template.AbstractTemplate;
import com.gexin.rp.sdk.template.LinkTemplate;
import com.gexin.rp.sdk.template.NotificationTemplate;
import com.gexin.rp.sdk.template.StartActivityTemplate;
import com.gexin.rp.sdk.template.TransmissionTemplate;
import com.gexin.rp.sdk.template.style.Style0;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;

import me.chanjar.weixin.mp.bean.result.WxMpUser;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

/**
 * 商城通知服务类
 */
public class NotifyService {
	
	private final Log logger = LogFactory.getLog(NotifyService.class);
	
	@Autowired
	private LitemallOrderService orderService;
	@Autowired
	private LitemallOrderGoodsService orderGoodsService;
	@Autowired
	private LitemallUserService userService;
	@Autowired
	private JavaMailSender javaMailSender;
	@Autowired
	private LitemallShopService shopService;
	@Autowired
	private SysUserService SysuserService;
	@Autowired
	private SysPushMsgMapper sysPushMsgMapper;
    @Autowired
    private TaskService taskService;
    @Autowired
    private printSnTaskService printSnTaskService;
	@Autowired
	private WxPayService wxPayService;
	@Autowired
	private TioWebSocketServerBootstrap bootstrap;
	@Autowired
	private LitemallAdminService AdminService;
	
	@Autowired
	private RedisCache redisCache;
	
	
    private MailSender mailSender;
    private String sendFrom;
    private String sendTo;
    
    private String appId;
    private String appKey;
    private String appSecret;
    private String masterSecret;
    private String url;
    

	private SmsSender smsSender;
    private List<Map<String, String>> smsTemplate = new ArrayList<>();

    private List<Map<String, String>> wxTemplate = new ArrayList<>();

    public boolean isMailEnable() {
        return mailSender != null;
    }

    public boolean isSmsEnable() {
        return smsSender != null;
    }

    
    
    /**
     * 推送订单信息给后台管理
     * 现在是全部通知管理员
     */
    @Async
    public void pushWebSocketUser() {
        //服务器发送到客户端的Packet都是WsResponse
        Message tioSendMessage = new Message();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        tioSendMessage.setReceiveTime(sdf.format(new Date()));
        tioSendMessage.setMsg("您有新的订单，请注意查收！");
        tioSendMessage.setMsgType(1);
        tioSendMessage.setSendType(1);
        WsResponse wsResponse = WsResponse.fromText(JSONArray.toJSONString(tioSendMessage), "UTF-8");
    	//Tio.sendToAll(bootstrap.getServerTioConfig(), wsResponse);
        TioWebSocket.sendToAdmin(bootstrap.getServerTioConfig(), wsResponse,AdminService.all());
    }
    
    /**
     * 推送订单退款信息到打印机
     * @param shopId
     * @param orderSn
     */
    @Async
    public void pushRefundOrderInfo(Integer shopId,String orderSn) {
    	LitemallShop shop = shopService.getOneByShopID(shopId);
    	SysUser user = SysuserService.getOneById(shop.getAdminId().longValue());
    	if(user.getPrintSn() == null) {
    		return;
    	}
    	if(user.getPrintType() == 0) {
    		return;
    	}
    	//订单信息
    	LitemallOrder order = getOrderDetail(orderSn);
    	
    	if(user.getPrintType() == 1) {//飞鹅云打印机
    		FeieService.printRefundOrderInfo(user.getPrintSn(),order,shop);
    	}
    	if(user.getPrintType() == 2) {//芯烨云打印机
    		XinhuaService.printRefundOrderInfo(user.getPrintSn(), order, shop);
    	}
    	
    	
    	//修改订单状态 退款成功
    	//这个接口是用户下单立马申请退款（1分钟内）后台应该也是立马给予他退款
    	//给用户退款，如果超过一分钟，用户只能联系商家，商家同意退款后，商家在app操作退款
    	
		if (order == null) {
			return;
		}
		// 微信退款
		WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
		wxPayRefundRequest.setOutTradeNo(order.getOrderSn());
		wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());
		// 元转成分
		Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();
		wxPayRefundRequest.setTotalFee(totalFee);
		wxPayRefundRequest.setRefundFee(totalFee);

		WxPayRefundResult wxPayRefundResult;
		try {
			wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);
		} catch (WxPayException e) {
			logger.error(e.getMessage(), e);
			return;
		}
		if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {
			logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
			return;
		}
		if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {
			logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
			return;
		}

		LocalDateTime now = LocalDateTime.now();
		// 设置订单取消状态
		order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);
		order.setEndTime(now);
		// 记录订单退款相关信息
		order.setRefundAmount(order.getActualPrice());
		order.setRefundType("微信退款接口");
		order.setRefundContent(wxPayRefundResult.getRefundId());
		order.setRefundTime(now);
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			throw new RuntimeException("更新数据已失效");
		}
		
		//printSnTaskService.removeTask(new OrderUnpaidTask2(orderSn,order.getShipChannel(),3));
    }
    
    /**
     * 推送订单信息到云打印机
     * @param shopId
     * @param orderSn
     */
    @Async
    public void pushPrintOrderInfo(Integer shopId,String orderSn,String shipSn) {
    	LitemallShop shop = shopService.getOneByShopID(shopId);
    	SysUser user = SysuserService.getOneById(shop.getAdminId().longValue());
    	if(user.getPrintType() == 0) {
    		return;
    	}
    	if(user.getPrintSn() == null) {
    		return;
    	}
    	//订单信息
    	LitemallOrder orderDetail = getOrderDetail(orderSn);
    	//订单详情
    	List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderDetail.getId());
    	String result = "";
    	if(user.getPrintType() == 1) {//飞鹅云打印机
    		result = FeieService.printOrderInfo(user.getPrintSn(),orderDetail,orderGoodsList,shop,shipSn);
    	}
    	if(user.getPrintType() == 2) {//芯烨云打印机
    		result = XinhuaService.printOrderInfo(user.getPrintSn(), orderDetail, orderGoodsList, shop, shipSn);
    	}
    	//将打印返回值存到缓存
    	//redisCache.setCacheObject("shop_print_"+orderDetail.getShopId(), result);
    	//orderDetail.setShipChannel(result);
    	//orderService.updateWithOptimisticLocker(orderDetail);
    	
    	//修改订单状态 开始配送中
    	//延迟处理
    	/*
    	Integer Dtime = 15;
    	if(!StringUtils.isEmpty(shop.getDeliveryTime())) {
    		Dtime = Integer.parseInt(shop.getDeliveryTime());
    	}
    	String deliveryTime = shop.getDeliveryTime();
    	if(!StringUtils.isEmpty(deliveryTime)) {
    		Dtime = Integer.parseInt(deliveryTime);//配送时间30分钟 5分钟左右出餐，20分钟左右配送到学门，5分钟左右配送到用户手上
    	}
    	//统一设置 5分钟 10分钟 15分钟 20分钟出餐完配送
    	Integer resTime = Dtime/3;
    	if(resTime<5) {
    		resTime = 5;
    	}*/
    	//taskService.removeTask(new OrderUnpaidTask2(orderSn,result,Dtime));
    	
    	//加入延迟任务，检查订单是否打印 设置5分钟去检验
    	printSnTaskService.addTask(new OrderUnpaidTask2(orderSn,result,3));
    	/*
    	try {
			Thread.sleep(15000);//10s
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	/*
    	boolean res = FeieService.selectPrintState(result);
    	if(res) {
    		logger.info("商家订单开始接单---订单已接单---" + result);
    		orderDetail.setOrderStatus(OrderUtil.STATUS_MAKE);
    		orderService.updateWithOptimisticLocker(orderDetail);
    	}*/
    }
    
	public LitemallOrder getOrderDetail(String orderSn) {
		return orderService.findBySn(orderSn);
	}
	
	/**
     * 对单个用户推送消息
     *
     * @return
     */
    @Async
    public void pushToSingle(Integer shopId) {
    	
    	LitemallShop shop = shopService.getOneByShopID(shopId);
    	SysUser user = SysuserService.getOneById(shop.getAdminId().longValue());
    	if(user.getCid() == null) {
    		return;
    	}
    	
        IGtPush push = new IGtPush(url, appKey, masterSecret);

        SingleMessage message = new SingleMessage();
        message.setOffline(true);
        // 离线有效时间，单位为毫秒，可选
        message.setOfflineExpireTime(24 * 3600 * 1000);
        message.setData(notificationTemplateDemo("您有新的订单消息，请注意查收！"));
        // 可选，1为wifi，0为不限制网络环境。根据手机处于的网络情况，决定是否下发
        message.setPushNetWorkType(0);
        // 厂商下发策略；1: 个推通道优先，在线经个推通道下发，离线经厂商下发(默认);2: 在离线只经厂商下发;3: 在离线只经个推通道下发;4: 优先经厂商下发，失败后经个推通道下发;
        message.setStrategyJson("{\"default\":4,\"ios\":4,\"st\":4}");
        Target target = new Target();
        target.setAppId(appId);
        //单个用户唯一标志
        target.setClientId(user.getCid());
        IPushResult ret = null;
        SysPushMsg msgPo = new SysPushMsg();
        msgPo.setClientId(user.getCid());//app clientid
        msgPo.setClientType(0);// 客户端类型：0-android;1-ios
        msgPo.setContent("您有新的订单消息，请注意查收！");
        msgPo.setPushTime(LocalDateTime.now());//推送时间
        
        try {
            ret = push.pushMessageToSingle(message, target);
        } catch (RequestException e) {
            e.printStackTrace();
            ret = push.pushMessageToSingle(message, target, e.getRequestId());
        }
        ///'推送状态：0-未推送；1-推送成功；2-推送失败；3-服务器响应异常；',
        if (ret != null) {
        	msgPo.setPushStatus(1);
        	msgPo.setPushResultDesc(ret.getResponse().toString());
            //System.out.println(ret.getResponse().toString());
        } else {
        	msgPo.setPushStatus(3);
        	msgPo.setPushResultDesc("服务器响应异常");
            System.out.println("服务器响应异常");
        }
        msgPo.setPushLoop(1);
        msgPo.setAddTime(LocalDateTime.now());
        //保存推送记录
        sysPushMsgMapper.insert(msgPo);
        
        
        //websocket 推送订单消息
        //服务器发送到客户端的Packet都是WsResponse
        Message tioSendMessage = new Message();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        tioSendMessage.setReceiveTime(sdf.format(new Date()));
        tioSendMessage.setMsg("您有新的订单，请注意查收！");
        tioSendMessage.setMsgType(1);
        tioSendMessage.setSendType(1);
        WsResponse wsResponse = WsResponse.fromText(JSONArray.toJSONString(tioSendMessage), "UTF-8");
    	//Tio.sendToAll(bootstrap.getServerTioConfig(), wsResponse);
        TioWebSocket.sendToMerchant(bootstrap.getServerTioConfig(), wsResponse, user.getUserName().toString());
        try {
			Thread.sleep(11000);
			//再次执行websocket推送
			TioWebSocket.sendToMerchant(bootstrap.getServerTioConfig(), wsResponse, user.getUserName().toString());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    @Async
    public void pushToSingle(Integer shopId, String msg) {
    	
    	LitemallShop shop = shopService.getOneByShopID(shopId);
    	SysUser user = SysuserService.getOneById(shop.getAdminId().longValue());
    	if(user.getCid() == null) {
    		return;
    	}
    	
        IGtPush push = new IGtPush(url, appKey, masterSecret);

        SingleMessage message = new SingleMessage();
        message.setOffline(true);
        // 离线有效时间，单位为毫秒，可选
        message.setOfflineExpireTime(24 * 3600 * 1000);
        message.setData(notificationTemplateDemo(msg));
        // 可选，1为wifi，0为不限制网络环境。根据手机处于的网络情况，决定是否下发
        message.setPushNetWorkType(0);
        // 厂商下发策略；1: 个推通道优先，在线经个推通道下发，离线经厂商下发(默认);2: 在离线只经厂商下发;3: 在离线只经个推通道下发;4: 优先经厂商下发，失败后经个推通道下发;
        message.setStrategyJson("{\"default\":4,\"ios\":4,\"st\":4}");
        Target target = new Target();
        target.setAppId(appId);
        //单个用户唯一标志
        target.setClientId(user.getCid());
        IPushResult ret = null;
        SysPushMsg msgPo = new SysPushMsg();
        msgPo.setClientId(user.getCid());//app clientid
        msgPo.setClientType(0);// 客户端类型：0-android;1-ios
        msgPo.setContent(msg);
        msgPo.setPushTime(LocalDateTime.now());//推送时间
        
        try {
            ret = push.pushMessageToSingle(message, target);
        } catch (RequestException e) {
            e.printStackTrace();
            ret = push.pushMessageToSingle(message, target, e.getRequestId());
        }
        ///'推送状态：0-未推送；1-推送成功；2-推送失败；3-服务器响应异常；',
        if (ret != null) {
        	msgPo.setPushStatus(1);
        	msgPo.setPushResultDesc(ret.getResponse().toString());
            //System.out.println(ret.getResponse().toString());
        } else {
        	msgPo.setPushStatus(3);
        	msgPo.setPushResultDesc("服务器响应异常");
            System.out.println("服务器响应异常");
        }
        msgPo.setPushLoop(1);
        msgPo.setAddTime(LocalDateTime.now());
        //保存推送记录
        sysPushMsgMapper.insert(msgPo);
    }
    
    //通知模板设置
    private NotificationTemplate notificationTemplateDemo(String msg/*, String phoneNumOrCid,String orderNum*/) {

        NotificationTemplate template = new NotificationTemplate();
        template.setAppId(appId);
        template.setAppkey(appKey);
        // 透传消息设置，1为强制启动应用，客户端接收到消息后就会立即启动应用；2为等待应用启动
        template.setTransmissionType(1);
        //透传内容，不在通知栏中展示，自定义内容，开发者自行处理，不支持转义字符
        template.setTransmissionContent(msg);
        Style0 style = new Style0();
        // 设置通知栏标题与内容
        style.setTitle("新订单");
        style.setText(msg);
        // 配置通知栏图标
        style.setLogo("icon.png");
        // 配置通知栏网络图标
//        style.setLogoUrl(pushMessage.getIconUrl());
        // 设置通知是否响铃，震动，或者可清除
        style.setRing(true);
        style.setVibrate(true);
        style.setClearable(true);
        style.setChannel("默认channel");
        style.setChannelName("默认channel名称");
        style.setChannelLevel(3);//3：有声音，有震动，锁屏和通知栏中都显示，通知唤醒屏幕。（推荐）
        template.setStyle(style);
        // 设置定时展示时间，安卓机型可用
        // template.setDuration("2019-08-16 11:40:00", "2019-08-16 12:24:00");
        // 消息覆盖
        //template.setNotifyid(pushMessage.getMsgId()); // 在消息推送的时候设置自定义的notifyid。如果需要覆盖此条消息，则下次使用相同的notifyid发一条新的消息。客户端sdk会根据notifyid进行覆盖。
        return template;
    }
    /**
     * 批量单推
     * 当单推任务较多时，推荐使用该接口，可以减少与服务端的交互次数。
     */
    @Async
    public void pushToSingleBatch(List<SysPushMsg> msgPos) {
    	IGtPush push = new IGtPush(url, appKey, masterSecret);
        IBatch batch = push.getBatch();
        IPushResult ret = null;
        try {
            //构建客户a的透传消息a
            for (SysPushMsg msgPo : msgPos) {
                constructClientTransMsg(msgPo.getClientId(), batch, msgPo.getContent());
            }
            ret = batch.submit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                ret = batch.retry();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        if (ret != null) {
            System.out.println(ret.getResponse().toString());
        } else {
            System.out.println("服务器响应异常");
        }
    }
    
    
    /**
     * 透传消息,消息传递到客户端只有消息内容，展现形式由客户端自行定义
     * 注：ios端只支持透传消息
     *
     * @param content
     * @return
     */
    public TransmissionTemplate getTransmissionTemplate(String content) {
        TransmissionTemplate template = new TransmissionTemplate();
        template.setAppId(appId);
        template.setAppkey(appKey);
        //透传消息设置，1为强制启动应用，客户端接收到消息后就会立即启动应用；2为等待应用启动
        template.setTransmissionType(2);
        template.setTransmissionContent(content);
        return template;
    }
    
    public SingleMessage getSingleMessage(AbstractTemplate template) {
        SingleMessage message = new SingleMessage();
        message.setData(template);
        // 设置消息离线，并设置离线时间
        message.setOffline(true);
        // 离线有效时间，单位为毫秒
        message.setOfflineExpireTime(72 * 3600 * 1000);
        message.setPriority(1);
        // 判断客户端是否wifi环境下推送。1为仅在wifi环境下推送，0为不限制网络环境，默认不限
        message.setPushNetWorkType(0);
        // 厂商下发策略；1: 个推通道优先，在线经个推通道下发，离线经厂商下发(默认);2: 在离线只经厂商下发;3: 在离线只经个推通道下发;4: 优先经厂商下发，失败后经个推通道下发;
        message.setStrategyJson("{\"default\":4,\"ios\":4,\"st\":4}");
        return message;
    }
    
    public void constructClientTransMsg(String cid, IBatch batch, String content) throws Exception {
        AbstractTemplate template = getTransmissionTemplate(content);
        SingleMessage message = getSingleMessage(template);
        // 设置推送目标，填入appid和clientId
        Target target = new Target();
        target.setAppId(appId);
        target.setClientId(cid);
        batch.add(message, target);
    }
    
    /**
     * 短信消息通知
     *
     * @param phoneNumber 接收通知的电话号码
     * @param message     短消息内容，这里短消息内容必须已经在短信平台审核通过
     */
    @Async
    public void notifySms(String phoneNumber, String message) {
        if (smsSender == null)
            return;

        smsSender.send(phoneNumber, message);
    }

    /**
     * 短信模版消息通知
     *
     * @param phoneNumber 接收通知的电话号码
     * @param notifyType  通知类别，通过该枚举值在配置文件中获取相应的模版ID
     * @param params      通知模版内容里的参数，类似"您的验证码为{1}"中{1}的值
     */
    @Async
    public void notifySmsTemplate(String phoneNumber, NotifyType notifyType, String[] params) {
        if (smsSender == null) {
            return;
        }

        String templateIdStr = getTemplateId(notifyType, smsTemplate);
        if (templateIdStr == null) {
            return;
        }

        smsSender.sendWithTemplate(phoneNumber, templateIdStr, params);
    }

    /**
     * 以同步的方式发送短信模版消息通知
     *
     * @param phoneNumber 接收通知的电话号码
     * @param notifyType  通知类别，通过该枚举值在配置文件中获取相应的模版ID
     * @param params      通知模版内容里的参数，类似"您的验证码为{1}"中{1}的值
     * @return
     */
    public SmsResult notifySmsTemplateSync(String phoneNumber, NotifyType notifyType, String[] params) {
        if (smsSender == null)
            return null;

        return smsSender.sendWithTemplate(phoneNumber, getTemplateId(notifyType, smsTemplate), params);
    }
    
    public String getOrderInfo(Integer id) {
    	
    	String html = "<!DOCTYPE html>\r\n" + 
    			"\r\n" + 
    			"<html>\r\n" + 
    			"\r\n" + 
    			"<head>\r\n" + 
    			"\r\n" + 
    			"<meta charset=\"UTF-8\">\r\n" + 
    			"\r\n" + 
    			"<title></title>\r\n" + 
    			"\r\n" + 
    			"</head>\r\n" + 
    			"\r\n" + 
    			"<style type=\"text/css\">\r\n" + 
    			"\r\n" + 
    			"table {\r\n" + 
    			"    border-collapse: collapse;\r\n" + 
    			"    border-spacing: 0;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTableAuto{\r\n" + 
    			"    width:1200px;\r\n" + 
    			"    margin:20px auto;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTable{\r\n" + 
    			"    border: 1px solid #e0e6ed;\r\n" + 
    			"    font-size: 16px;\r\n" + 
    			"    width:100%;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTableTitle{\r\n" + 
    			"    padding:10px 20px;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTable td {\r\n" + 
    			"    height: 40px;\r\n" + 
    			"    min-width: 0px;\r\n" + 
    			"    box-sizing: border-box;\r\n" + 
    			"    vertical-align: middle;\r\n" + 
    			"    position: relative;\r\n" + 
    			"    border-bottom: 1px solid #e0e6ed;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTable_header tr {\r\n" + 
    			"    background-color: #efeff1;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTable_header th {\r\n" + 
    			"    min-width: 0;\r\n" + 
    			"    box-sizing: border-box;\r\n" + 
    			"    text-overflow: ellipsis;\r\n" + 
    			"    vertical-align: middle;\r\n" + 
    			"    position: relative;\r\n" + 
    			"    border-bottom: 1px solid #e0e6ed;\r\n" + 
    			"    border-right: 1px solid #e0e6ed;\r\n" + 
    			"    padding: 10px 0px;\r\n" + 
    			"    white-space: nowrap;\r\n" + 
    			"    overflow: hidden;\r\n" + 
    			"    font-weight: bold;\r\n" + 
    			"    text-align: -internal-center;\r\n" + 
    			"  }\r\n" + 
    			"\r\n" + 
    			"  .cloudTable_body tr td {\r\n" + 
    			"    height: 40px;\r\n" + 
    			"    text-align: center;\r\n" + 
    			"    white-space: nowrap;\r\n" + 
    			"    overflow: hidden;\r\n" + 
    			"    text-overflow: ellipsis;\r\n" + 
    			"    text-align: center;\r\n" + 
    			"    box-sizing: border-box;\r\n" + 
    			"    -webkit-box-sizing: border-box;\r\n" + 
    			"    font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTable_body tr td {\r\n" + 
    			"    box-sizing: border-box;\r\n" + 
    			"    white-space: nowrap;\r\n" + 
    			"    overflow: hidden;\r\n" + 
    			"    text-overflow: ellipsis;\r\n" + 
    			"    text-align: center;\r\n" + 
    			"    border-right: 1px solid #e0e6ed;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudMtxTable_body{\r\n" + 
    			"    height:402px;\r\n" + 
    			"    width:100%;\r\n" + 
    			"    overflow-y: auto;\r\n" + 
    			"    border-bottom: 1px solid #e0e6ed;\r\n" + 
    			"  }\r\n" + 
    			"\r\n" + 
    			"  .data-cell {\r\n" + 
    			"    padding-left: 15px;\r\n" + 
    			"    padding-right: 15px;\r\n" + 
    			"    font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;\r\n" + 
    			"  }\r\n" + 
    			"  .cloudTable_body tr:hover {\r\n" + 
    			"    background-color: #c5e8fe;\r\n" + 
    			"  }\r\n" + 
    			"</style>\r\n" + 
    			"\r\n" + 
    			"<body>\r\n" + 
    			"\r\n" + 
    			"<div class=\"cloudTableAuto\">";
    	
        LitemallOrder order = orderService.findById(id);
        List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);
        UserVo user = userService.findUserVoById(order.getUserId());
        
        html = html + "<p>订单编号：<span>"+ order.getOrderSn() +"</span></p>";
        
        String orderStatusText = OrderUtil.orderStatusText(order);
        html = html + "<p>订单状态：<span>"+ orderStatusText +"</span></p>";
        
        html = html + "<p>用户名称：<span>"+ user.getNickname() +"</span></p>";
        
        html = html + "<p>收货地址：<span>(收货人)"+ order.getConsignee() + "(手机号码)" + order.getMobile() + "(地址)" + order.getAddress() +"</span></p>";
        
        html = html + "<p>用户留言：<span>"+ order.getMessage() +"</span></p>";
        
        html = html + "    <table class=\"cloudTable cloudMtxTableHead\">\r\n" + 
        		"      <colgroup>\r\n" + 
        		"        <col width=\"60\">\r\n" + 
        		"        <col width=\"220px\">\r\n" + 
        		"        <col width=\"230px\">\r\n" + 
        		"        <col width=\"90px\">\r\n" + 
        		"        <col width=\"90px\">\r\n" + 
        		"      </colgroup>\r\n" + 
        		"      <thead class=\"cloudTable_header\">\r\n" + 
        		"        <tr>\r\n" + 
        		"          <th>序号</th>\r\n" + 
        		"          <th>商品名称</th>\r\n" + 
        		"          <th>金额</th>\r\n" + 
        		"          <th>购买数量</th>\r\n" + 
        		"          <th>图片</th>\r\n" + 
        		"        </tr>\r\n" + 
        		"      </thead>\r\n" + 
        		"    </table >\r\n" + 
        		"    <div class=\"cloudMtxTable_body\">";
        
        html = html +"";
        
        for(int i=0;i<orderGoods.size();i++) {
        	LitemallOrderGoods o = orderGoods.get(i);
        	String center = "      <table class=\"cloudTable\"  style=\"table-layout:fixed\">\r\n" + 
        			"        <colgroup >\r\n" + 
        			"        <col width=\"60\">\r\n" + 
        			"        <col width=\"220px\">\r\n" + 
        			"        <col width=\"230px\">\r\n" + 
        			"        <col width=\"90px\">\r\n" + 
        			"        <col width=\"90px\">\r\n" + 
        			"        </colgroup>\r\n" + 
        			"        <tbody class=\"cloudTable_body \">\r\n" + 
        			"          <tr>\r\n" + 
        			"            <td>xuhao</td>\r\n" + 
        			"            <td class=\"data-cell\">shangpin<span></span></td>\r\n" + 
        			"            <td class=\"data-cell\">jine</td>\r\n" + 
        			"            <td>shuliang</td>\r\n" + 
        			"            <td>\r\n" + 
        			"				<img src=\"tupian\" style=\"width:60px;height:60px;\" />\r\n" + 
        			"			</td>\r\n" + 
        			"          </tr>\r\n" + 
        			"        </tbody></table>";
        	String one = center.replaceFirst("xuhao", (i+1)+"");
        	
        	String two = one.replaceFirst("shangpin", o.getGoodsName());
        	
        	String three = two.replaceFirst("jine", o.getPrice().toString());
        	
        	String four = three.replaceFirst("shuliang", o.getNumber().toString());
        	
        	String five = four.replaceFirst("tupian", o.getPicUrl());
        	
        	html = html + five;
        }
        
        //html 结尾
        html = html + "    </div>\r\n" + 
        		"  </div>\r\n" + 
        		"\r\n" + 
        		"</body>\r\n" + 
        		"\r\n" + 
        		"</html>";
        
        return html;
    }
    
    /**
     * 邮件消息通知,
     * 接收者在spring.mail.sendto中指定
     *
     * @param subject 邮件标题
     * @param content 邮件内容
     */
    @Async
    public void notifyMail(String subject, String content) {
        if (mailSender == null)
            return;
        
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(sendFrom);
        message.setTo(sendTo);
        message.setSubject(subject);
        message.setText(content);
        mailSender.send(message);
    }
    
    @Async
    public void notifyMail(String subject, Integer id) throws MessagingException {
        if (mailSender == null)
            return;
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true); 
        message.setSubject(subject);
        message.setFrom(sendFrom);
        message.setTo(sendTo);
        
        String content = getOrderInfo(id);
        
        message.setText(content,true);
        
        javaMailSender.send(mimeMessage);
        
        
        /*
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(sendFrom);
        message.setTo(sendTo);
        message.setSubject(subject);
        String content = getOrderInfo(id);
        message.setText(content);
        mailSender.send(message);*/
    }

    private String getTemplateId(NotifyType notifyType, List<Map<String, String>> values) {
        for (Map<String, String> item : values) {
            String notifyTypeStr = notifyType.getType();

            if (item.get("name").equals(notifyTypeStr))
                return item.get("templateId");
        }
        return null;
    }

    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void setSendFrom(String sendFrom) {
        this.sendFrom = sendFrom;
    }

    public void setSendTo(String sendTo) {
        this.sendTo = sendTo;
    }

    public void setSmsSender(SmsSender smsSender) {
        this.smsSender = smsSender;
    }

    public void setSmsTemplate(List<Map<String, String>> smsTemplate) {
        this.smsTemplate = smsTemplate;
    }

    public void setWxTemplate(List<Map<String, String>> wxTemplate) {
        this.wxTemplate = wxTemplate;
    }
    
	public void setAppId(String appId) {
		this.appId = appId;
	}


	public void setAppKey(String appKey) {
		this.appKey = appKey;
	}


	public void setAppSecret(String appSecret) {
		this.appSecret = appSecret;
	}


	public void setMasterSecret(String masterSecret) {
		this.masterSecret = masterSecret;
	}


	public void setUrl(String url) {
		this.url = url;
	}
}
